/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frssl_crypto.c                                     */
/*  NOTE      =                                                    */
/*  DATE      = 2015/11/18 by guojq                                */
/*******************************************************************/
#include <stdio.h>
#include <string.h>

#include "frcomm.h"
#include "frmem.h"
#include "frlog.h"
#include "frbase64.h"

#define BROADA_SSL_KEY      "f(j#0"
#define BROADA_KEY_MD5      "dc4634ee6c75ab1c1c593ae4887f3e56"

#define PRIVATE_KEY         "900150983cd24fb0d6963f7d28e17f72"

static int __keyED(char *p_src, int i_inlen, char **pp_out, int *p_i_outlen)
{
    char arr_encrypt_key[33];
    char *p_out_tmp = NULL;
    int i,j = 0;
    
    if (p_src == NULL)
        return 0;
        
    snprintf(arr_encrypt_key, sizeof(arr_encrypt_key), "%s", BROADA_KEY_MD5);
    
    p_out_tmp = (char *)frmalloc(i_inlen + 1);
    if (p_out_tmp == NULL)
        return 0;
    memset(p_out_tmp, 0x00, i_inlen + 1);
    
    *p_i_outlen = i_inlen;
    for (i=0;i<i_inlen;i++)
    {
        if (j == strlen(arr_encrypt_key))
            j = 0;
        p_out_tmp[i] = p_src[i] ^ arr_encrypt_key[j];
        j++;
    }
    
    *pp_out = p_out_tmp;
    return 1;
}

/*******************************************************************************
*  FUNC     :  加密
*  ARGS     :  p_in                 需要加密的字符串
*           :  pp_out               加密后的字符串
*           :  p_i_out              加密后的字符串长度
*  RTN      :  FR_SUCC              
*              FR_FAIL              
*  NOTE     :  入力的参数比出力的参数小一倍
*******************************************************************************/
int __encrypt(char *p_in, char **pp_out, int *p_i_out)
{
    char arr_encrypt_key[33];
    char *p_tmp = NULL;
    int i, j=0, k=0;
    
    //对随机数做md5加密最佳arr_encrypt_key
    
    snprintf(arr_encrypt_key, sizeof(arr_encrypt_key), "%s", PRIVATE_KEY);
//    printf("encrypt md5=[%s]\n", arr_encrypt_key);
    p_tmp = (char *) frmalloc(strlen(p_in)*2+1);
    if (p_tmp == NULL)
        return FR_FAIL;
    
    memset(p_tmp, 0x00, strlen(p_in)*2+1);
    
    for(i=0;i<strlen(p_in);i++)
    {
        if (strlen(arr_encrypt_key) == j)
            j = 0;
        p_tmp[k++] = arr_encrypt_key[j];
        p_tmp[k++] = p_in[i] ^ arr_encrypt_key[j];
        j++;
    }
    
    if (__keyED(p_tmp, k, pp_out, p_i_out) == 0)
    {
        frfree(p_tmp);
        return FR_FAIL;
    }
    frfree(p_tmp);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  解密
*  ARGS     :  p_in                 需要解密的字符串
*           :  i_inlen              需要解密的字符串长度
*           :  pp_out               解密后的字符串
*  RTN      :  FR_SUCC              
*              FR_FAIL              
*  NOTE     :  入力的参数比出力的参数大一倍
*******************************************************************************/
int __decrypt(char *p_in, int i_inlen, char **pp_out)
{
    char *p_tmp;
    char *p_out_tmp;
    int i, j=0, i_out;
    
    if (__keyED(p_in, i_inlen, &p_tmp, &i_out) == 0)
    {
        printf("keyED failed\n");
        return FR_FAIL;
    }
    
    p_out_tmp = (char *) frmalloc(i_inlen/2 + 1);
    if (p_out_tmp == NULL)
    {
        frfree(p_tmp);
        return FR_FAIL;
    }
    memset(p_out_tmp, 0x00, i_inlen/2 + 1);
    for (i=0;i<i_inlen;i++)
    {
        i++;
        if (i >= i_inlen)
            break;
        p_out_tmp[j++] = p_tmp[i] ^ p_tmp[i-1];
    }
    *pp_out = p_out_tmp;
    frfree(p_tmp);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  加密
*  ARGS     :  p_in                 需要加密的字符串
*           :  pp_out               加密后的字符串
*  RTN      :  FR_SUCC              
*              FR_FAIL              
*  NOTE     :  
*******************************************************************************/
int ssl_config_encrypt(char *p_in, char **pp_out)
{
    char *p_encode = NULL;
    char *p_out_tmp = NULL;
    int i_encode_out = 0;
    
    if (p_in == NULL || *p_in == '\0' || pp_out == NULL)
        return FR_FAIL;
    
    if (__encrypt(p_in, &p_encode, &i_encode_out) != FR_SUCC)
    {
        return FR_FAIL;
    }
    
    //2次加密，base64加密
    p_out_tmp = frbase64_encode((unsigned char *)p_encode, i_encode_out);
    if (p_out_tmp == NULL)
    {
        frfree(p_encode);
        return FR_FAIL;
    }
    frfree(p_encode);
    *pp_out = p_out_tmp;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  解密
*  ARGS     :  p_in                 需要解密的字符串
*           :  pp_out               解密后的字符串
*  RTN      :  FR_SUCC              
*              FR_FAIL              
*  NOTE     :  
*******************************************************************************/
int ssl_config_decrypt(char *p_in, char **pp_out)
{
    char *p_decode = NULL;
    char *p_out_tmp = NULL;
    int i_decode = 0;
    
    if (p_in == NULL || *p_in == '\0' || pp_out == NULL)
        return FR_FAIL;
        
    p_decode = (char *) frbase64_decode(p_in, &i_decode);
    if (p_decode == NULL)
    {
        return FR_FAIL;
    }
    if (__decrypt(p_decode, i_decode, &p_out_tmp) != FR_SUCC)
    {
        frfree(p_decode);
        return FR_FAIL;
    }
    frfree(p_decode);
    *pp_out = p_out_tmp;
    
    return FR_SUCC;
}
